﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using MockCommon;
using MockDataTransferObject;
using System.Data;
using MockBusiness;
using System.Globalization;

namespace Presentation.AdminPresentation
{
    public partial class Import : System.Web.UI.Page
    {
        private MessageBusiness _messageBusiness;
        private RoleBusiness _roleBusiness;
        private ContractTypeBusiness _contractTypeBusiness;
        private ClientBusiness _clientBusiness;
        private ConsultantBusiness _consultantBusiness;
        private ContractBusiness _contractBusiness;
        private UserBusiness _userBusiness;
        private Button _uploadButton;
        private FileUpload _csvFileUpload;
        private ListView _listView;
        private Button _applyButton;
        private Button _exportButton;
        private Label _warningLabel;
        private Label _errorLabel;
        private Label _successLabel;

        protected void Page_Init(object sender, EventArgs e)
        {
            try
            {
                _messageBusiness = MessageBusiness.RetrieveInstance();
                _roleBusiness = RoleBusiness.RetrieveInstance();
                _contractTypeBusiness = ContractTypeBusiness.RetrieveInstance();
                _clientBusiness = ClientBusiness.RetrieveInstance();
                _consultantBusiness = ConsultantBusiness.RetrieveInstance();
                _contractBusiness = ContractBusiness.RetrieveInstance();
                _userBusiness = UserBusiness.RetrieveInstance();
                _uploadButton = (Button)ImportControl.FindControl("UploadButton");
                _csvFileUpload = (FileUpload)ImportControl.FindControl("CsvFileUpload");
                _listView = (ListView)ImportControl.FindControl("ContractListView");
                _applyButton = (Button)ImportControl.FindControl("ApplyButton");
                _exportButton = (Button)ImportControl.FindControl("ExportButton");
                _warningLabel = (Label)Master.FindControl("WarningLabel");
                _errorLabel = (Label)Master.FindControl("ErrorLabel");
                _successLabel = (Label)Master.FindControl("SuccessLabel");
                _applyButton.OnClientClick = "if(!getChecked(this)) return false";
                _exportButton.OnClientClick = "if(!getChecked(this)) return false";
                _uploadButton.Click += new EventHandler(UploadButton_Click);
                _applyButton.Click += new EventHandler(ApplyButton_Click);
                _exportButton.Click += new EventHandler(ExportButton_Click);
            }
            catch (MockException exception)
            {
                Application["error"] = exception;
                Response.Redirect("../Error.aspx");
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (Session["user"] == null)
            {
                Response.Redirect("../LogOn.aspx");
            }
            else
            {
                User user = Session["user"] as User;
                if (user.Role.RoleName != "Admin")
                {
                    Server.Transfer("../NotAuthorized.aspx");
                }
            }
            TitleLabel.Text = "Import CSV";
            ErrorText.Text = "";
            ResultPanel.Visible = false;
            if (IsPostBack)
            {
                _warningLabel.Text = "";
                _errorLabel.Text = "";
                _successLabel.Text = "";
            }
        }

        protected void UploadButton_Click(object sender, EventArgs e)
        {
            try
            {
                bool isValid = false;
                string filePath = null;
                if (_csvFileUpload.HasFile)
                {
                    string[] allowedExtension = { ".csv" };
                    filePath = _csvFileUpload.FileName;
                    string fileExtension = Path.GetExtension(filePath);
                    foreach (string extension in allowedExtension)
                    {
                        if (fileExtension == extension)
                        {
                            isValid = true;
                        }
                    }
                }

                if (isValid)
                {
                    _applyButton.Visible = true;
                    _exportButton.Visible = true;
                    CsvDataSet dataSet = new CsvDataSet(_csvFileUpload.FileContent, Constant.PatternCsvFile);
                    DataTable dataTable = dataSet.Tables[0];
                    Session["ImportCsvData"] = dataTable;
                    _listView.DataSource = dataTable;
                    _listView.DataBind();
                }
                else
                {
                    _errorLabel.Text = "File is invalid";
                }
            }
            catch (MockException exception)
            {
                _applyButton.Visible = false;
                _exportButton.Visible = false;
                ResultPanel.Visible = true;
                ErrorText.Text = exception.ExceptionMessage;
            }
        }

        protected void RegenerateButton_Click(object sender, EventArgs e)
        {
            object errorSource = Session["ImportFailedRow"];
            if (errorSource != null)
            {
                Dictionary<int, string> rowErrors = (Dictionary<int, string>)errorSource;
                int rowErrorsCount = rowErrors.Count;
                int[] indexs = new int[rowErrorsCount];
                int i = 0;
                foreach (int index in rowErrors.Keys)
                {
                    indexs[i] = index;
                    i++;
                }

                if (rowErrorsCount > 0)
                {
                    ExportData(indexs);
                }
            }
        }

        protected void ExportButton_Click(object sender, EventArgs e)
        {
            string value = ValueHidden.Value;
            if (value != null)
            {
                ExportData(value);
            }
        }

        protected void ApplyButton_Click(object sender, EventArgs e)
        {
            //initialize
            string[] cells = null;
            string clientUsername;
            string consultantUsername;
            string contractTypeName;
            string content;
            DateTime startDate;
            DateTime endDate;
            string contractorFirstName;
            string contractorLastName;
            DateTime contractorBirthdate;
            bool contractorGender;
            string contractorTelephone1;
            string contractorTelephone2;
            string contractorBranch;
            string contractorSortCode;
            int emailInDay;
            Dictionary<int, string> affectedRows = new Dictionary<int, string>();
            Dictionary<int, string> failedRows = new Dictionary<int, string>();
            try
            {
                string value = ValueHidden.Value;
                if (value != null)
                {
                    MockDataTransferObject.Contract contractObject;
                    Contractor contractorObject;
                    User userObject;
                    Role roleObject;
                    Consultant consultantObject;
                    ContractType contractTypeObject;
                    Client clientObject;
                    string[] rows = value.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
                    int rowsLength = rows.Length;
                    string row = "";
                    for (int i = 0; i < rowsLength; i++)
                    {
                        row = rows[i];
                        if (row == "\r")
                        {
                            continue;
                        }
                        cells = row.Split(new char[] { '\t' }, StringSplitOptions.None);
                        clientUsername = cells[0];
                        consultantUsername = cells[1];
                        contractTypeName = cells[2];
                        content = cells[3];
                        if (!DateTime.TryParse(cells[4], out startDate))
                        {
                            failedRows.Add(i, "Start date is not valid datetime");
                            continue;
                        }
                        if (!DateTime.TryParse(cells[5], out endDate))
                        {
                            failedRows.Add(i, "End date is not valid datetime");
                            continue;
                        }
                        if (endDate < startDate)
                        {
                            failedRows.Add(i, "End date must greater than start date");
                            continue;
                        }
                        contractorFirstName = cells[6];
                        contractorLastName = cells[7];
                        if (!DateTime.TryParse(cells[8], out contractorBirthdate))
                        {
                            failedRows.Add(i, "Birth date is not valid datetime");
                            continue;
                        }
                        if (!Boolean.TryParse(cells[9], out contractorGender))
                        {
                            failedRows.Add(i, "Gender is not valid boolean");
                            continue;
                        }
                        contractorTelephone1 = cells[10];
                        contractorTelephone2 = cells[11];
                        contractorBranch = cells[12];
                        contractorSortCode = cells[13];
                        if (!Int32.TryParse(cells[14], out emailInDay))
                        {
                            failedRows.Add(i, "Day receive email is not valid integer");
                            continue;
                        }
                        //client
                        object clientIdValue = _clientBusiness.GetClientIdByUserName(clientUsername);
                        if (clientIdValue == null)
                        {
                            failedRows.Add(i, "Client was not existed");
                            continue;
                        }
                        clientObject = _clientBusiness.GetById(clientIdValue);
                        //consultant
                        object consultantIdValue = _consultantBusiness.GetConsultantIdByUserName(consultantUsername);
                        if (consultantIdValue == null)
                        {
                            failedRows.Add(i, "Consultant was not existed");
                            continue;
                        }
                        consultantObject = _consultantBusiness.GetById(consultantIdValue);                                                
                        //contract type
                        object contractTypeIdValue = _contractTypeBusiness.GetContractTypeIdByContractTypeName(contractTypeName);
                        if (contractTypeIdValue == null)
                        {
                            failedRows.Add(i, "ContractType was not existed");
                            continue;
                        }
                        contractTypeObject = _contractTypeBusiness.GetById(contractTypeIdValue);
                        //role of contractor
                        object roleIdValue = _roleBusiness.GetRoleIdByRoleName("Contractor");
                        if (roleIdValue == null)
                        {
                            failedRows.Add(i, "Role was not existed");
                            continue;
                        }
                        roleObject = _roleBusiness.GetById(roleIdValue);
                        //user of contractor
                        userObject = new MockDataTransferObject.User();
                        userObject.UserId = Guid.NewGuid();
                        string username = _userBusiness.GenerateUserName(contractorFirstName, contractorLastName);
                        if (username == null)
                        {
                            failedRows.Add(i, "Username can't be generated");
                            continue;
                        }
                        string password = UserBusiness.GeneratePassword();
                        userObject.UserName = username;
                        userObject.Role = roleObject;
                        userObject.Password = password;
                        userObject.Email = null;
                        userObject.IsActive = true;
                        //contractor
                        contractorObject = new Contractor();
                        contractorObject.ContractorId = Guid.NewGuid();
                        contractorObject.User = userObject;
                        contractorObject.FirstName = contractorFirstName;
                        contractorObject.LastName = contractorLastName;
                        contractorObject.BirthDate = contractorBirthdate;
                        contractorObject.Gender = contractorGender;
                        contractorObject.Telephone1 = contractorTelephone1;
                        contractorObject.Telephone2 = contractorTelephone2;
                        contractorObject.Branch = contractorBranch;
                        contractorObject.SortCode = contractorSortCode;
                        contractorObject.DayInWeek = emailInDay;
                        //contract
                        contractObject = new MockDataTransferObject.Contract();
                        contractObject.ContractId = Guid.NewGuid();
                        contractObject.Contractor = contractorObject;
                        contractObject.Consultant = consultantObject;
                        contractObject.ContractType = contractTypeObject;
                        contractObject.Client = clientObject;
                        contractObject.Content = content;
                        contractObject.StartDate = startDate;
                        contractObject.EndDate = endDate;
                        contractObject.IsActive = true;
                        try
                        {
                            _contractBusiness.Insert(contractObject);
                            Notify(clientUsername, consultantUsername, contractTypeName, content, startDate, endDate, contractObject, username, password);
                            affectedRows.Add(i, "Contract was created");
                        }
                        catch (MockException exception)
                        {
                            failedRows.Add(i, exception.ExceptionMessage);
                        }
                    }
                }
            }
            catch (IndexOutOfRangeException exception)
            {
                ResultPanel.Visible = true;
                ErrorText.Text = exception.Message;
            }
            catch (FormatException exception)
            {
                ResultPanel.Visible = true;
                ErrorText.Text = exception.Message;
            }
            finally
            {
                ResultPanel.Visible = true;
                SuccessMessage.Text = String.Format(CultureInfo.CurrentCulture, "({0}) successful ", affectedRows.Count);
                FailureMessage.Text = String.Format(CultureInfo.CurrentCulture, "({0}) failed ", failedRows.Count);
                Session["ImportFailedRow"] = failedRows;
                ErrorRepeater.DataSource = failedRows;
                ErrorRepeater.DataBind();
                SuccessRepeater.DataSource = affectedRows;
                SuccessRepeater.DataBind();
                _successLabel.Text = SuccessMessage.Text;
                _errorLabel.Text = FailureMessage.Text;
            }
        }

        private void Notify(string clientUsername, string consultantUsername, string contractTypeName, string content, DateTime startDate, DateTime endDate, MockDataTransferObject.Contract contractObject, string username, string password)
        {
            User fromUser = Session["user"] as User;
            User toUser = contractObject.Client.User;
            Message message = new Message();
            string contentMail = @"Dear <b>{0}</b><br/>
                                   Contract has been created for you, some infomations as below:<br/>
                                   <div class=""contentMail"">
                                   -Contract type: <b>{1}</b>.<br/>
                                   -Consultant: <b>{2}</b>.<br/>
                                   -Client: <b>{3}</b>.<br/>
                                   -Contractor: <b>{4}</b>.<br/>
                                   -Contractor password: <b>{5}</b>.<br/>
                                   -Content: <br/>
                                   <b>{6}</b>.<br/>
                                   -Start date: <b>{7}</b>.<br/>
                                   -End date: <b>{8}</b>.<br/>
                                   </div><br/>
                                   Now you can send these information for each contractor of you!<br/><br/>
                                   <b>CMS AutoMailer.</b><br/>
                                   <b>&</b>
                                   <b>Best Regards!</b>";
            message.MessageId = Guid.NewGuid();
            message.From = fromUser;
            message.To = toUser;
            message.Title = String.Format(CultureInfo.CurrentCulture, "<b>{0}</b> has created new contract", fromUser.UserName);
            message.Content = String.Format(CultureInfo.CurrentCulture, contentMail, toUser.UserName, contractTypeName, consultantUsername, clientUsername, username, password, content, startDate, endDate);
            message.IsRead = false;
            message.IsReceive = false;
            message.SendDate = DateTime.Now;
            _messageBusiness.Insert(message);
        }

        private void ExportData(int[] index)
        {
            string data = "";
            object dataSource = Session["ImportCsvData"];
            if (dataSource == null)
            {
                Response.Redirect("Import.aspx");
            }

            try
            {
                if (dataSource != null)
                {
                    DataTable dataTable = (DataTable)dataSource;
                    for (int i = 0; i < index.Length; i++)
                    {
                        DataRow row = dataTable.Rows[i];
                        data += row["hidden"];
                        data += "\n";
                    }
                    ExportData(data);
                }
            }
            catch (MockException exception)
            {
                ResultPanel.Visible = true;
                ErrorText.Text = exception.ExceptionMessage;
            }
        }

        private void ExportData(string data)
        {
            try
            {
                string content = ContractBusiness.MakeCsvContent(data);
                Response.ContentType = "application/octet-stream";
                Response.Write(content);
                Response.AddHeader("Content-Disposition", "attachment;filename=Data.csv");
                Response.End();
            }
            catch (HttpException exception)
            {
                _errorLabel.Text = exception.Message;
            }
        }
    }
}